﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Windows;
using System.ComponentModel;

namespace DataAccess
{
    public static class DataExtensions
    {
        static System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

        private static DataAccess.SPIWareIIIDataContext context;
        public static DataAccess.SPIWareIIIDataContext DataContext
        {
            get
            {
                if (context == null)
                {
                    //string conn = ConfigurationManager.ConnectionStrings["DataAccess.Properties.Settings.SPIWare3ConnectionString"].ConnectionString;
                    string conn = config.AppSettings.Settings["SPIWare3ConnectionString"].Value;
                    context = new DataAccess.SPIWareIIIDataContext(conn);
                }
                return context;
            }
        }

        public static void Save()
        {
            DataContext.SubmitChanges();
        }

        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> enumerable)
        {
            var col = new ObservableCollection<T>();
            foreach (var cur in enumerable)
            {
                col.Add(cur);
            }
            return col;
        }

        public static ObservableCollection<Part> GetByCustomer(this IEnumerable<Part> data, Customer customer)
        {
            return (from d in data
                    join cp in DataContext.CustomerParts on d.PartsId equals cp.PartsId
                    where cp.CustomerId == customer.CustomerId
                    orderby d.Description
                    select d).ToObservableCollection<Part>();
        }
        public static ObservableCollection<WorkOrder> GetByCustomer(this IEnumerable<WorkOrder> data, Customer customer)
        {
            return (from d in data
                    where d.CustomerId == customer.CustomerId
                    orderby d.DateDue
                    select d).ToObservableCollection<WorkOrder>();
        }

        public static ObservableCollection<WorkOrder> DisplayOnlyOpen(this IEnumerable<WorkOrder> data)
        {
            return (from d in data
                    where d.WorkOrderCompleted == false
                    orderby d.DateDue
                    select d).ToObservableCollection<WorkOrder>();
        }
    }
    //public partial class SPIWareIIIDataContext : System.Data.Linq.DataContext
    //{
    //    partial void OnCreated()
    //    {
    //        this.Connection.ConnectionString = ConfigurationSettings.AppSettings["SPIWare3ConnectionString"];
    //        //bool isDebug = Convert.ToBoolean(Properties.Settings.Default["DebugMode"]);
    //        //string conn = Convert.ToString(Properties.Settings.Default["SPIProduction"]);
    //        //if (isDebug) conn = Convert.ToString(Properties.Settings.Default["SPIDebug"]);
    //    }
    //}
    public partial class Customer
    {
        public string IdName { get { return string.Format("({0}) {1}", this.CustomerId, this.Name); } }
        public ObservableCollection<ContactInfo> ocContactInfos
        {
            get
            {
                return DataExtensions.ToObservableCollection<ContactInfo>(this._ContactInfos);
            }
            set { }
        }

        public override string ToString()
        {
            return this.Name;
        }
    }
    public partial class ContactInfo
    {
        public override string ToString()
        {
            if (this.AddressLine1 == null || this.AddressLine1 == string.Empty) return string.Format("{0} {1}", this.Name, this.Telephone);
            return string.Format("{0}, {1} {2}", this.AddressLine1, this.Locality, this.StateProvince);
        }
    }
    public partial class WorkOrder
    {
        public string Status { get { return string.Format("( {0} )", this.WorkOrderCompleted ? "Completed" : "Open"); } }
        public bool IsEditable { get { return !this.WorkOrderCompleted; } }
        List<MachineProduction> _workOrderProductions;
        public ObservableCollection<MachineProduction> ocProduction
        {
            get { return DataExtensions.ToObservableCollection<MachineProduction>(this.MachineProductions); }
            set { }
        }

        public int oQuantity
        {
            get { return CorrectedQuantity > 0 ? (int)CorrectedQuantity : (int)QuantityOrdered; }
            set
            {
                if (QuantityOrdered > 0) CorrectedQuantity = value;
                else QuantityOrdered = value;
                OnQuantityOrderedChanged();
                OnCorrectedQuantityChanged();
            }
        }

        public override string ToString()
        {
            //return string.Format("({0}) {1} {2}"
            //    , this.WorkOrderId
            //    , this.CorrectedQuantity > 0 ? this.CorrectedQuantity : this.QuantityOrdered
            //    , this.Part != null ? this.Part.Description : string.Empty);
            return string.Format("({0}) {1} {2} {3}"
                , this.WorkOrderId
                , this.Customer != null ? this.Customer.Name : string.Empty
                , this.CustomerPO != null ? this.CustomerPO : string.Empty
                , this.Part != null ? this.Part.PartNumber : string.Empty);
        }
    }
    public partial class Part
    {
        public override string ToString()
        {
            return string.Format("({0}) {1}", this.PartNumber, this.Description);
        }

        #region Dynamic Calculations
        public void Recalc()
        {
            //NOTE: AverageCycleTime = TargetCycleTime
            //NOTE: txtOtherPrice = PricePerBox
        }
        public void CalcOpCostPerPart()
        {
            OpCostPerPart = (double)PressOpCost / PartsPerHour_AS != null && (double)PartsPerHour_AS > 0
                ? (double)PartsPerHour_AS
                : 1;
        }
        public void CalcBoxesPerPallet()
        {
            BoxesPerPallet = PartsPerPallet / (PartsPerBox > 0 ? PartsPerBox : 1);//residual:calcTTLPackagingPiecePerPart
        }
        public void CalcDyeCostPerPart()
        {
            //DyeMixRatio as int or DyeMixRatio/100 ???
            DyeCostPerPart = PartWeight / 100 * (DyeMixRatio / 100) * DyeCostPerLB; //residual: calcResinDyePricePerPart
        }
        public void CalcMoldSetupCost()
        {
            MoldSetupCost = MoldSetupTime * 20;//residual: calcCostStartPress
        }
        public void CalcPartsPerHour()
        {
            PartsPerHour = 3600 / TargetCycleTime * PartsPerShot;

        }
        public void CalcNaturalResin()
        {
            NaturalResin = MaterialType.CostPerLB * PartWeight; //residual: calcResinDyePricePerPart
        }
        public void CalcResinDyePricePerPart()
        {
            double dResin = ((double)PartWeight - (double)DyeMixRatio) / (100 / (double)PartWeight);
            ResinDyePricePerPart = (dResin / 100 * (DyeMixRatio / 100) * DyeCostPerLB) + (MaterialType.CostPerLB * dResin); //residual: calcTTLCostPrePartMaterialPackaging
        }
        public void CalcStartupScrapPrice()
        {
            StartupScrapPrice = (StartupScrap / 100) * DyeMixRatio / 100 * DyeCostPerLB + (StartupScrap * MaterialType.CostPerLB);
        }

        public void CalcPartsPerHour_AS()
        {
            PartsPerHour_AS = 3600 / AverageCycleTime_AS * PartsPerShot;
            //residual:calcTTLCostAvgCycleTime, calcAfterSetupAvgCycleTime, calcAfterMaterialsRunTarget, calcAfterMaterialsAvgCycleTime
        }
        public void CalcTTLPackagingPiecePerPart()
        {
            TTLPackagingPiecePerPart = (BoxPrice / PartsPerBox) + (4 / PartsPerPallet) + AQ41Price + (PricePerBox / PartsPerBox);
            //residual:calcTTLCostPrePartMaterialPackaging
        }
        public void CalcTTLCostPrePartMaterialPackaging()
        {
            TTLCostPrePartMaterialPackaging = (ResinDyePricePerPart + MaterialCost + TTLPackagingPiecePerPart);
            //residual:calcTTLPrePartMaterialPackagingLabor, calcAfterMaterialsRunTarget, calcAfterMaterialsAvgCycleTime
        }
        public void CalcLaborSecondPerPart()
        {
            LaborSecondPerPart = AverageCycleTime_AS / PartsPerShot;//residual:calcLaborTTLPerPart
        }
        public void CalcLaborTTLPerPart()
        {
            LaborTTLPerPart = LaborSecondPerPart * 0.0042;//residual:calcTTLPrePartMaterialPackagingLabor, calcAfterSetupRunTarget, calcAfterSetupAvgCycleTime
        }
        public void CalcOverheadFactor()
        {
            OverheadFactor = 0.36 / PartsPerShot;
        }
        public void CalcCostStartPress()
        {
            CostStartPress = MoldSetupCost + StartupScrapPrice;//residual:calcTTLCostPartAverage
        }
        public void CalcTTLPrePartMaterialPackagingLabor()
        {
            TTLPrePartMaterialPackagingLabor = OpCostPerPart + TTLCostPrePartMaterialPackaging + LaborTTLPerPart;
            //residual:calcTTLCostPartAverage
        }
        public void CalcTTLCostPartAverage()
        {
            TTLCostPartAverage = CostStartPress / 1000 + TTLPrePartMaterialPackagingLabor;
            //residual:calcTTLCostRunTarget, calcTTLCostAvgCycleTime, calcAfterSetupRunTarget, calcAfterSetupAvgCycleTime
        }
        public void CalcTTLCostRunTarget()
        {
            TTLCostRunTarget = (Price - TTLCostPartAverage) * PartsPerHour;
        }
        public void CalcTTLCostAvgCycleTime()
        {
            TTLCostAvgCycleTime = (Price - TTLCostPartAverage) * PartsPerHour_AS;
        }
        public void CalcAfterSetupRunTarget()
        {
            AfterSetupRunTarget = (Price - TTLCostPartAverage + LaborTTLPerPart + OpCostPerPart) * PartsPerHour;
        }
        public void CalcAfterSetupAvgCycleTime()
        {
            AfterSetupAvgCycleTime = (Price - TTLCostPartAverage + LaborTTLPerPart + OpCostPerPart) * PartsPerHour_AS;
        }
        public void CalcAfterMaterialsRunTarget()
        {
            AfterMaterialsRunTarget = (Price - TTLCostPrePartMaterialPackaging) * PartsPerHour;
        }
        public void CalcAfterMaterialsAvgCycleTime()
        {
            AfterMaterialsAvgCycleTime = (Price - TTLCostPrePartMaterialPackaging) * PartsPerHour_AS;
        }
        #endregion

    }
    public partial class CustomerPart
    {
        public override string ToString()
        {
            return Part.Description;
        }
    }
    public partial class MachinePress
    {
        public override string ToString()
        {
            //var AllRuns = (from m in MachineProductions
            //               where ((DateTime)m.EndTime).Date == DateTime.Now.Date
            //               select new { m.Shift, m.RunTime });

            //List<TimeSpan> GraveyardRuns = new List<TimeSpan>();
            //List<TimeSpan> DayRuns = new List<TimeSpan>();
            //List<TimeSpan> SwingRuns = new List<TimeSpan>();
            //foreach (var t in AllRuns)
            //{
            //    if ((WorkShifts)t.Shift == WorkShifts.Grave) GraveyardRuns.Add(t.RunTime);
            //    if ((WorkShifts)t.Shift == WorkShifts.Day) DayRuns.Add(t.RunTime);
            //    if ((WorkShifts)t.Shift == WorkShifts.Swing) SwingRuns.Add(t.RunTime);
            //}

            //TimeSpan GraveyardRun = ((List<TimeSpan>)GraveyardRuns).Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal.Add(t));
            //TimeSpan DayRun = ((List<TimeSpan>)DayRuns).Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal.Add(t));
            //TimeSpan SwingRun = ((List<TimeSpan>)SwingRuns).Aggregate(TimeSpan.Zero, (subtotal, t) => subtotal.Add(t));

            //return string.Format("{0} | {1} | {2} | {3}", this.MachineNumber, GraveyardRun, DayRun, SwingRun);

            return string.Format("( {0} ) {1}", this.MachineNumber, this.PressSize);
        }
    }
    public partial class MachineProduction
    {
        public TimeSpan RunTime { get { return (this.EndTime == null ? DateTime.Now : (DateTime)this.EndTime) - (DateTime)this.StartTime; } }
        public int RunCount { get { return this.EndCount - this.StartCount; } }
        public override string ToString()
        {
            if (this.StartTime == null) this.StartTime = DateTime.Now.Date;

            return string.Format("({0}) {1} {2}",
                this.MachinePress != null ? this.MachinePress.MachineNumber : string.Empty,
                this.RunCount,
                this.RunTime);
        }
    }
    public partial class MaterialType
    {
        public override string ToString()
        {
            return MaterialType1;
        }
    }
    public partial class ApplicationUser
    {
        public override string ToString()
        {
            return string.Format("({0}) {1}", this.UserId, this.UserName);
        }

    }
}
